﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace DataBaseTools.Common
{
    public static class SafeClipboard
    {
        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool CloseClipboard();

        [DllImport("user32.dll")]
        private static extern bool OpenClipboard(IntPtr hWndNewOwner);

        [DllImport("user32.dll")]
        private static extern bool EmptyClipboard();

        /// <summary>
        /// 超强健壮的剪贴板写入方法
        /// </summary>
        public static void SetDataAtomic(string format, object data, int maxRetries = 5, int baseDelay = 100)
        {
            if (Application.Current.Dispatcher.CheckAccess())
            {
                InternalSetData(format, data, maxRetries, baseDelay);
            }
            else
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    InternalSetData(format, data, maxRetries, baseDelay);
                });
            }
        }

        private static void InternalSetData(string format, object data, int maxRetries, int baseDelay)
        {
            for (int i = 0; i < maxRetries; i++)
            {
                try
                {
                    // 暴力模式：先清空剪贴板所有权
                    ForceCleanClipboard();

                    // 设置数据
                    Clipboard.SetData(format, data);
                    return;
                }
                catch (COMException ex) when (ex.ErrorCode == -2147221040)
                {
                    // 指数退避策略
                    int delay = baseDelay * (int)Math.Pow(2, i);
                    Thread.Sleep(delay);

                    // 最后一次尝试前进行深度清理
                    if (i == maxRetries - 2)
                        KillInterferingProcesses();
                }
            }
            throw new ClipboardException($"剪贴板写入失败，最终尝试后仍被占用");
        }

        private static void ForceCleanClipboard()
        {
            try
            {
                // 三重清理保障
                OpenClipboard(IntPtr.Zero);
                EmptyClipboard();
                CloseClipboard();
            }
            catch { /* 吞掉所有异常 */ }
        }

        private static void KillInterferingProcesses()
        {
            // 常见剪贴板占用进程
            string[] suspectProcesses = { "ditto", "clipbrd", "rdpclip", "teamviewer" };

            foreach (var proc in Process.GetProcesses())
            {
                try
                {
                    foreach (var badProcess in suspectProcesses)
                    {
                        if (proc.ProcessName.ToUpper().Contains(badProcess.ToUpper()))
                        {
                            proc.Kill();
                            Thread.Sleep(50);
                        }
                    }
                }
                catch { /* 无权限则跳过 */ }
            }
        }
    }

    public class ClipboardException : Exception
    {
        public ClipboardException(string msg) : base(msg) { }
    }

}
